﻿#!/usr/bin/env python3

import logging, os.path, paramiko, time, re

# 1.创建一个logger
logger = logging.getLogger()
logger.setLevel(logging.INFO)  # Log等级总开关,默认level是WARNING,低于该级别的就不输出了,级别排序: CRITICAL > ERROR > WARNING > INFO > DEBUG

# 2.创建一个handler，用于写入日志文件
"""
time.time():从1970年1月1日0分0时0秒起至当前时间，经过的浮点数
time.localtime()：转换为time.struct_time类型的对象的秒数
time.strftime() 函数根据指定的格式把一个时间字符串解析为时间元组
"""
log_time = time.strftime('%Y_%m_%d-%H_%M_%S', time.localtime(time.time()))
log_path = os.path.dirname(os.getcwd())   # os.getcwd() 用于返回当前工作目录
log_name = log_path + log_time + '.log'
log_file = log_name
fh = logging.FileHandler(log_file, mode='w')
fh.setLevel(logging.INFO)  # 输出到file的log等级的开关
# output to console
ch = logging.StreamHandler()
ch.setLevel(logging.WARNING)

# 3.定义handler的输出格式
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
fh.setFormatter(formatter)

# 4.将logger添加到handler里面
logger.addHandler(fh)
# output to console
ch.setFormatter(formatter)
logger.addHandler(ch)

def if_desc_cisco_ssh2_log(ip, port, username, password, cmd_list, enable='', verbose=True):
    try:
        ssh = paramiko.SSHClient()
        ssh.load_system_host_keys()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip, port, username, password, timeout=3, compress=True)
        chan = ssh.invoke_shell()
        time.sleep(1)
        x = chan.recv(2048).decode()
        logging.warning('%s connect success ' % ip)

        if enable and '>' in x:
            chan.send('enable'.encode() + b'\n')
            time.sleep(1)
            chan.send(enable.encode() + b'\n')
            time.sleep(1)
        elif not enable and '>' in x:
            print('need enable password')
            return

        # cisco and h3c diff
        chan.send('terminal length 0'.encode() + b'\n')
        time.sleep(1)
        chan.send('terminal no monitor'.encode() + b'\n')
        time.sleep(1)

        # cisco diff
        chan.send('show version'.encode() + b'\n')
        time.sleep(2)
        rackreply1 = chan.recv(40960).decode()
        if verbose:
            # print(rackreply1)


            if 'Cisco IOS Software' in rackreply1:
                print(f'The system of {ip} is IOS, loading......')
                chan.send('show cdp nei detail'.encode() + b'\n')
                time.sleep(5)
                rackreply2 = chan.recv(40960).decode()
                if verbose:
                    # print(rackreply2)
                    ifnumber_list = re.findall(r'Interface:\s+(\S+),.*', rackreply2)   # + 出现一次或多次
                    print(f'The interface list is below: \n{ifnumber_list}')
                    time.sleep(1)
                    ifnbr_list = re.findall(r'Device ID:\s+(\S+)', rackreply2)
                    print(f'The interface Nbr is below: \n{ifnbr_list}')
                    time.sleep(1)
                    raw_dict = dict(zip(ifnumber_list,ifnbr_list))
                    print(f'The dict is below: \n{raw_dict}')
                    time.sleep(1)

                    print('The raw data of agent is below:')
                    if_desc_file = open('if_desc_agent.txt', 'w')
                    for k,v in raw_dict.items():
                        print(k,v)
                        if_desc_file.write('interface ' + str(k) + '\n' + ' desc ' + str(v) + '\n')
                    if_desc_file.close()
                    time.sleep(1)

                    chan.send('conf t'.encode() + b'\n')
                    time.sleep(0.5)
                    if_desc_cmd = open('if_desc_agent.txt', 'r')
                    for f in if_desc_cmd:
                        chan.send(f.encode().strip() + b'\n')
                        x = chan.recv(40960).decode()
                        if verbose:
                            print(x)
                            time.sleep(0.5)
                            logging.warning('execute: \n%s' % x)

                    chan.send('end'.encode() + b'\n')
                    time.sleep(1)
                    chan.send('write'.encode() + b'\n')
                    time.sleep(3)
                    logging.warning(f'The cfg of {ip} is saved, start next...')


            elif 'Cisco Nexus Operating System (NX-OS) Software' in rackreply1:
                print(f'The system of {ip} is NXOS, loading......')

                chan.send('show cdp nei detail'.encode() + b'\n')
                time.sleep(5)
                rackreply2 = chan.recv(40960).decode()
                if verbose:
                    # print(rackreply2)
                    ifnumber_list = re.findall(r'Interface:\s*(\S+),.*', rackreply2)   # * 出现零次或多次
                    print(f'The interface list is below: \n{ifnumber_list}')
                    time.sleep(1)
                    ifnbr_list = re.findall(r'Device ID:\s*(\S+)', rackreply2)
                    print(f'The interface Nbr is below: \n{ifnbr_list}')
                    time.sleep(1)
                    raw_dict = dict(zip(ifnumber_list,ifnbr_list))
                    print(f'The dict is below: \n{raw_dict}')
                    time.sleep(1)

                    print('The raw data of agent is below:')
                    if_desc_file = open('if_desc_agent.txt', 'w')
                    for k,v in raw_dict.items():
                        print(k,v)
                        if_desc_file.write('interface ' + str(k) + '\n' + ' desc ' + str(v) + '\n')
                    if_desc_file.close()
                    time.sleep(1)

                    chan.send('conf t'.encode() + b'\n')
                    time.sleep(0.5)
                    if_desc_cmd = open('if_desc_agent.txt', 'r')
                    for f in if_desc_cmd:
                        chan.send(f.encode().strip() + b'\n')
                        x = chan.recv(40960).decode()
                        if verbose:
                            print(x)
                            logging.warning('execute: \n%s' % x)

                    chan.send('end'.encode() + b'\n')
                    time.sleep(1)
                    chan.send('copy running-config startup-config'.encode() + b'\n')
                    time.sleep(3)
                    logging.warning(f'The cfg of {ip} is saved, start next...')


            else:
                print(f'The system of {ip} is unknown, ending......')

        chan.close()
        ssh.close()
        logging.warning(f'The job of {ip} is over, start next...')

    except Exception as e:
        print(f'{ip} connect failed ', e)
        logging.warning('%s connect failed ' % ip)

if __name__ == '__main__':
    import all_authen
    username = all_authen.login_user
    password = all_authen.login_token

    ip_list = open('if_desc_ips.txt', 'r')
    for ip in ip_list:
        if_desc_cisco_ssh2_log(ip.strip(), 22, username, password, ['show clock'], enable='cisco', verbose=True)
